/**
 * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.opsli.modulars.customer.record.service.impl;


import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.opsli.api.wrapper.customer.record.CustomerRecordModel;
import org.opsli.common.exception.ServiceException;
import org.opsli.core.base.service.impl.CrudServiceImpl;
import org.opsli.core.options.EmailConfigFactory;
import org.opsli.core.utils.GuaGuaUtil;
import org.opsli.modulars.customer.record.entity.CustomerRecord;
import org.opsli.modulars.customer.record.mapper.CustomerRecordMapper;
import org.opsli.modulars.customer.record.service.ICustomerRecordService;
import org.opsli.plugins.email.EmailPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;


/**
 * BrokerRecord Service Impl
 *
 * @author guagua
 * @date 2025-06-12 13:51:39
 */
@Slf4j
@Service
@EnableScheduling
public class CustomerRecordServiceImpl extends CrudServiceImpl<CustomerRecordMapper, CustomerRecord, CustomerRecordModel>
        implements ICustomerRecordService {

    private static final String REMINDER_KEY_PREFIX = "reminder:customer:";
    @Autowired(required = false)
    private CustomerRecordMapper mapper;
    @Autowired
    private EmailPlugin emailPlugin;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void addReminder(String brokerId, Date reminderTime, String email, String content) {
        // 生成随机key
        String randomKey = UUID.randomUUID().toString().replace("-", "");
        String key = REMINDER_KEY_PREFIX + randomKey;

        ReminderInfo reminderInfo = new ReminderInfo();
        reminderInfo.setCustomerId(brokerId);
        reminderInfo.setEmail(email);
        reminderInfo.setContent(content);
        reminderInfo.setReminderTime(reminderTime);// sk-cpoccwhmcarkwhtwawwbcqdqqrclyygiayzrfceuonxoipbr
        reminderInfo.setProcessed(false); // 初始状态为未处理

        // 计算过期时间（毫秒），增加5分钟缓冲时间
        long expireTime = reminderTime.getTime() - System.currentTimeMillis() + (5 * 60 * 1000);
        if (expireTime > 0) {
            // 使用JSON序列化存储
            String jsonStr = JSON.toJSONString(reminderInfo);
            GuaGuaUtil.set(key, jsonStr, expireTime, TimeUnit.MILLISECONDS);
            log.info("Add reminder task: brokerId={}, key={}, expireTime={}", brokerId, key, expireTime);
        } else {
            log.error("Add reminder task failed: brokerId={}, key={}, expireTime={}", brokerId, key, expireTime);
            throw new ServiceException(500, "Add reminder task failed");
        }
    }

    @Scheduled(cron = "0 */1 * * * ?")
    @Override
    public void checkAndSendReminders() {
        log.info("开始检查提醒...");
        try {
            // 获取所有提醒key
            Set<String> keys = GuaGuaUtil.keys(REMINDER_KEY_PREFIX + "*");
            if (keys == null || keys.isEmpty()) {
                log.info("没有任何提醒");
                return;
            }

            for (String key : keys) {
                Object obj = GuaGuaUtil.get(key);
                if (obj instanceof String) {
                    try {
                        ReminderInfo reminderInfo = JSON.parseObject((String) obj, ReminderInfo.class);

                        // 检查是否已处理
                        if (reminderInfo.isProcessed()) {
                            log.info("这个已经处理过了: {}", key);
                            continue;
                        }

                        // 检查提醒时间是否已到
                        long currentTime = System.currentTimeMillis();
                        long reminderTime = reminderInfo.getReminderTime().getTime();
                        if (reminderTime > currentTime) {
                            log.info("时间还没到: {}, time left: {} ms",
                                    key, reminderTime - currentTime);
                            continue;
                        }

                        log.info("发送邮件到: {}, 内容: {}",
                                reminderInfo.getEmail(), reminderInfo.getContent());
                        // 发送邮件提醒
                        String subject = "提醒 通知";
                        String htmlContent = "<h3>提醒通知</h3>" +
                                "<p>" + reminderInfo.getContent() + "</p>" +
                                "<p>提醒时间: " + reminderInfo.getReminderTime() + "</p>";
                        emailPlugin.send(reminderInfo.getEmail(), subject, htmlContent,
                                EmailConfigFactory.INSTANCE.getConfig());

                        // 标记为已处理
                        reminderInfo.setProcessed(true);
                        String jsonStr = JSON.toJSONString(reminderInfo);
                        GuaGuaUtil.set(key, jsonStr, 5, TimeUnit.MINUTES);

                        log.info("提醒成功: {}", key);
                    } catch (Exception e) {
                        log.error("解析提醒数据失败: {}", key, e);
                    }
                } else {
                    log.warn("数据格式错误 for key: {}", key);
                }
            }
        } catch (Exception e) {
            log.error("发送数据失败 reminders", e);
        }
        log.info("检查完成 reminders");
    }

    @Data
    public static class ReminderInfo implements java.io.Serializable {
        private String customerId;
        private String email;
        private String content;
        private Date reminderTime;
        private boolean processed; // 是否已处理
    }

}